package com.seng.resourcetycoon.gui.util;

import com.seng.resourcetycoon.core.entities.EventProbabilityPair;
import com.seng.resourcetycoon.core.entities.RandomEvent;
import com.seng.resourcetycoon.core.enums.DifficultyLevel;
import com.seng.resourcetycoon.core.enums.RandomEventType;
import com.seng.resourcetycoon.manager.GameEnvironment;

import java.util.*;

public class EventGenerator {

    // 定义基础事件概率
    public static final double BASE_BOOST_PROBABILITY = 0.1;
    private static final double BASE_BREAKDOWN_PROBABILITY = 0.3;
    private static final double BASE_RESOURCE_SPAWN_PROBABILITY = 0.1;

    private final Random random = new Random();

    private final Map<DifficultyLevel, Map<Integer, List<EventProbabilityPair>>> eventMap;

    public EventGenerator() {
        eventMap = new HashMap<>();
        // 初始化事件映射，这里仅示例部分数据)
        DifficultyLevel[] levels = DifficultyLevel.values();
        for (int difficulty = 0; difficulty < levels.length; difficulty++) {
            eventMap.put(levels[difficulty], new HashMap<>());
            for (int level = 0; level < GameEnvironment.getInstance().getMaxGameRound(); level++) {
                eventMap.get(levels[difficulty]).put(level, new ArrayList<>());
                // 根据难度和关卡填充事件及其概率
                double[] probabilities = calculateEventProbabilities(difficulty,level+1);
                eventMap.get(levels[difficulty]).get(level).add(new EventProbabilityPair(new RandomEvent(RandomEventType.TOWER_BREAKDOWN),probabilities[1]));
                eventMap.get(levels[difficulty]).get(level).add(new EventProbabilityPair(new RandomEvent(RandomEventType.TOWER_BOOST), probabilities[0] ));
                eventMap.get(levels[difficulty]).get(level).add(new EventProbabilityPair(new RandomEvent(RandomEventType.RESOURCE_SPAWN), probabilities[2]));

            }
        }
    }

    /**
     * 计算各个事件基于难度级别和当前关卡数的概率。
     * @param difficultyLevel 当前关卡的难度等级。
     * @param currentLevel 当前关卡编号。
     * @return 一个包含提升、故障、资源生成概率的数组。
     * @throws IllegalArgumentException 如果难度级别或当前关卡数不合法。
     */
    public static double[] calculateEventProbabilities(int difficultyLevel, int currentLevel) throws IllegalArgumentException {
        // 参数验证
        validateParameters( currentLevel);

        // 调整关卡和难度级别
        int adjustedCurrentLevel = adjustLevel(currentLevel);
        int adjustedDifficultyLevel = adjustDifficulty(difficultyLevel);

        // 计算各种事件的概率
        double breakdownProbability = calculateProbability(BASE_BREAKDOWN_PROBABILITY, adjustedCurrentLevel, 0.01, 1);
        double boostProbability = calculateProbability(BASE_BOOST_PROBABILITY, adjustedDifficultyLevel, 0.01, adjustedCurrentLevel, 0.005);
        double resourceSpawnProbability = calculateProbability(BASE_RESOURCE_SPAWN_PROBABILITY, adjustedCurrentLevel, 0.01);

        return new double[]{breakdownProbability, boostProbability, resourceSpawnProbability};
    }

    // 验证难度级别和当前关卡数的参数
    private static void validateParameters( int currentLevel) throws IllegalArgumentException {
        if (currentLevel < 1) {
            throw new IllegalArgumentException("The current level number cannot be less than 1");
        }
    }

    // 调整关卡数值
    private static int adjustLevel(int level) {
        return Math.max(1, level);
    }

    // 调整难度级别数值
    private static int adjustDifficulty(int difficulty) {
        return Math.max(1, Math.min(10, difficulty));
    }

    // 计算概率的辅助方法
    private static double calculateProbability(double baseProbability, int levelOrDifficulty, double... adjustmentFactors) {
        double probability = baseProbability;
        for (double factor : adjustmentFactors) {
            probability += (levelOrDifficulty * factor);
        }
        probability = Math.max(0, Math.min(1, probability)); // 确保概率在0到1之间
        return probability;
    }

    /**
     * 生成事件，根据难度系数和关卡
     * @param difficultyLevel 难度系数
     * @param currentLevel 当前关卡
     * @return 一个根据难度和关卡随机选择的事件实例
     */
    public RandomEvent generateEvent(DifficultyLevel difficultyLevel, int currentLevel) {
        List<EventProbabilityPair> eventList = getEventListForDifficultyAndLevel(difficultyLevel, currentLevel);

        if (eventList.isEmpty()) {
            // 考虑到性能和恢复性，这里返回一个默认事件而不是抛出异常
            return new RandomEvent(RandomEventType.NONE);
        }

        RandomEvent selectedEvent = chooseRandomEvent(eventList);
        if (selectedEvent != null) {
            return selectedEvent;
        }

        // 理论上不会执行到这里，但作为保护措施
        return new RandomEvent(RandomEventType.NONE);
    }

    private List<EventProbabilityPair> getEventListForDifficultyAndLevel(DifficultyLevel difficultyLevel, int currentLevel) {
        // 从 eventMap 获取对应难度和关卡的事件列表，若不存在则返回空列表
        return eventMap.getOrDefault(difficultyLevel, Collections.emptyMap())
                .getOrDefault(currentLevel, Collections.emptyList());
    }

    private RandomEvent chooseRandomEvent(List<EventProbabilityPair> eventList) {
        double totalProbability = eventList.stream().mapToDouble(EventProbabilityPair::getProbability).sum();
        // 防止 totalProbability 为 0，确保随机选择的逻辑正常运行
        if (totalProbability == 0) {
            return null;
        }

        double randomValue = random.nextDouble() * totalProbability;
        double accumulatedProbability = 0;

        for (EventProbabilityPair pair : eventList) {
            accumulatedProbability += pair.getProbability();
            if (randomValue <= accumulatedProbability) {
                return pair.getEvent();
            }
        }

        return null; // 理论上不应该到达这里
    }
}